In this assignment you will develop your initial concept note into a draft of a full project proposal. Treat this assignment as a “dry run” for developing a proposal for a grant or fellowship application, or for your Ph.D. prospectus.

Your proposal should include at least the following sections and information.

Front matter: Descriptive title, your name, date, reference to “SYS 5581 Time Series & Forecasting, Spring 2021”.

Abstract: A very brief summary of the project.

1 Introduction

Give a narrative description of the problem you are addressing, and the methods you will use to address it. Provide context:

This work addresses the question: Why do people not use probabilistic forecasts for decision-making (Burnham and Anderson 2002)?

2 The data and the data-generating process

Describe the data set you will be analyzing, and where it comes from, how it was generated and collected. Identify the source of the data. Give a narrative description of the data-generating process: this piece is critical .

Since these will be time series data: identify the frequency of the data series (e.g., hourly, monthly), and the period of record.

esales <- dbGetQuery(db,'SELECT * from eia_elec_sales_va_all_m') # SQL code to retrieve data from a table in the remote database
# str(esales)
esales <- as_tibble(esales) # Convert dataframe to a 'tibble' for tidyverse work
# str(esales)
# Reference: https://arrow.apache.org/docs/r/
# if(!('arrow' %in% installed.packages())) install.packages('arrow')
library(arrow)
write_feather(esales, "esales.feather")
# Close connection -- this is good practice
dbDisconnect(db)
dbUnloadDriver(db_driver)

3 Exploratory data analysis

library(arrow)
esales <- read_feather("esales.feather")

str(esales)
tibble [233 × 4] (S3: tbl_df/tbl/data.frame)
 $ value: num [1:233] 8282 7839 8889 9368 9209 ...
 $ date : Date[1:233], format: "2020-05-01" "2020-04-01" "2020-03-01" "2020-02-01" ...
 $ year : int [1:233] 2020 2020 2020 2020 2020 2019 2019 2019 2019 2019 ...
 $ month: int [1:233] 5 4 3 2 1 12 11 10 9 8 ...

3.1 Provide a brief example of the data, showing how they are structured.

print(esales)
# References: https://www.tidyverse.org/, https://dplyr.tidyverse.org/

esales %>%
  filter(year == 2019) %>%
  filter(value > 9000) %>%
  print()

esales %>%
  group_by(month) %>%
  summarise(mean = mean(value)) -> mean_esales_by_month

esales %>%
  mutate(sales_TWh = value/1000) %>%
  select(-value)
  
# filter(data object, condition) : syntax for filter() command

3.2 Plot the time series.

#Reference: https://ggplot2.tidyverse.org/

ggplot(data=esales, aes(x=date,y=value)) + 
  geom_line() + xlab("Year") + ylab("Virginia monthly total electricity sales (GWh)")

# install.packages("tsibble")
library(tsibble) # Reference: https://tsibble.tidyverts.org/articles/intro-tsibble.html

esales %>% as_tsibble(index = date) -> esales_tbl_ts

print(esales_tbl_ts)
library(lubridate) # Make it easy to deal with dates

esales_tbl_ts %>% filter(month==3)

esales_tbl_ts %>% filter(month(date)==3)

esales_tbl_ts %>%
  select(date, sales_GWh = value) -> elsales_tbl_ts

print(elsales_tbl_ts)

3.3 Perform and report the results of other exploratory data analysis


hist(elsales_tbl_ts$sales_GWh, breaks=40)

# install.packages("feasts"), Reference: https://feasts.tidyverts.org/
library(feasts)

elsales_tbl_ts %>% 
  mutate(Month = yearmonth(date)) %>% 
  as_tsibble(index = Month) -> vaelsales_tbl_ts


vaelsales_tbl_ts %>% gg_season(sales_GWh, labels = "both") + ylab("Virginia electricity sales (GWh)")

# install.packages('tsibbledata')
library(tsibbledata)

aus_production

aus_production %>% gg_season(Electricity)


aus_production %>% gg_season(Beer)

NA
NA
vaelsales_tbl_ts %>% 
  gg_subseries(sales_GWh)


# aus_production %>% gg_subseries(Beer)
vaelsales_tbl_ts  %>% filter(month(Month) %in% c(3,6,9,12)) %>% gg_lag(sales_GWh, lags = 1:2)


vaelsales_tbl_ts  %>% filter(month(Month) == 1) %>% gg_lag(sales_GWh, lags = 1:2)

vaelsales_tbl_ts %>% ACF(sales_GWh) %>% autoplot()



# decompose(vaelsales_tbl_ts)
vaelsales_tbl_ts %>%
  model(STL(sales_GWh ~ trend(window=21) + season(window='periodic'), robust = TRUE)) %>%
  components() %>%
  autoplot()

vaelsales_tbl_ts %>%
  mutate(ln_sales_GWh = log(sales_GWh)) %>%
  model(STL(ln_sales_GWh ~ trend(window=21) + season(window='periodic'),
    robust = TRUE)) %>%
  components() %>%
  autoplot()

vaelsales_tbl_ts %>%
  features(sales_GWh, feat_stl)
vaelsales_tbl_ts %>%
  features(sales_GWh, feature_set(pkgs="feasts"))
`n_flat_spots()` is deprecated as of feasts 0.1.5.
Please use `longest_flat_spot()` instead.
This warning is displayed once every 8 hours.
Call `lifecycle::last_warnings()` to see where this warning was generated.

4 Example: Gross Domestic Product data

4.1 Exploratory data analysis

library(tsibbledata) # Data sets package

print(global_economy)
global_economy %>% filter(Country=="Sweden") %>% print()
global_economy %>%
  filter(Country=="Sweden") %>%
  autoplot(GDP) +
  ggtitle("GDP for Sweden") + ylab("$US billions")

4.2 Fitting data to simple models

global_economy %>% model(trend_model = TSLM(GDP ~ trend())) -> fit
7 errors (1 unique) encountered for trend_model
[7] 0 (non-NA) cases
fit
NA
NA
fit %>% filter(Country == "Sweden") %>% residuals()

fit %>% filter(Country == "Sweden") %>% residuals() %>% autoplot(.resid)

4.2.1 Work with ln(GDP)

global_economy %>%
  filter(Country=="Sweden") %>%
  autoplot(log(GDP)) +
  ggtitle("ln(GDP) for Sweden") + ylab("$US billions")

global_economy %>%
  model(trend_model = TSLM(log(GDP) ~ trend())) -> logfit
7 errors (1 unique) encountered for trend_model
[7] 0 (non-NA) cases
logfit %>% filter(Country == "Sweden") %>% residuals() %>% autoplot()
Plot variable not specified, automatically selected `.vars = .resid`

global_economy %>% model(trend_model = TSLM(log(GDP) ~ log(Population))) -> fit3
7 errors (1 unique) encountered for trend_model
[7] 0 (non-NA) cases
fit3 %>% filter(Country == "Sweden") %>% residuals() %>% autoplot()
Plot variable not specified, automatically selected `.vars = .resid`

5 Producing forecasts

fit %>% forecast(h = "3 years") -> fcast3yrs

fcast3yrs
NA

fcast3yrs %>% filter(Country == "Sweden", Year == 2020) %>% str()
fable [1 × 5] (S3: fbl_ts/tbl_ts/tbl_df/tbl/data.frame)
 $ Country: Factor w/ 263 levels "Afghanistan",..: 232
 $ .model : chr "trend_model"
 $ Year   : num 2020
 $ GDP    : dist [1:1] 
  ..$ 3:List of 2
  .. ..$ mu   : num 5.45e+11
  .. ..$ sigma: num 5.34e+10
  .. ..- attr(*, "class")= chr [1:2] "dist_normal" "dist_default"
  ..@ vars: chr "GDP"
 $ .mean  : num 5.45e+11
 - attr(*, "key")= tibble [1 × 3] (S3: tbl_df/tbl/data.frame)
  ..$ Country: Factor w/ 263 levels "Afghanistan",..: 232
  ..$ .model : chr "trend_model"
  ..$ .rows  : list<int> [1:1] 
  .. ..$ : int 1
  .. ..@ ptype: int(0) 
  ..- attr(*, ".drop")= logi TRUE
 - attr(*, "index")= chr "Year"
  ..- attr(*, "ordered")= logi TRUE
 - attr(*, "index2")= chr "Year"
 - attr(*, "interval")= interval [1:1] 1Y
  ..@ .regular: logi TRUE
 - attr(*, "response")= chr "GDP"
 - attr(*, "dist")= chr "GDP"
 - attr(*, "model_cn")= chr ".model"
fcast3yrs %>% 
  filter(Country=="Sweden") %>%
  autoplot(global_economy) +
  ggtitle("GDP for Sweden") + ylab("$US billions")

5.1 Model residuals vs. forecast errors

Model residuals:

Your data: \(y_1, y_2, \ldots, y_T\)

Fitted values: \(\hat{y}_1, \hat{y}_2, \ldots, \hat{y}_T\)

Model residuals: \(e_t = y_t - \hat{y}_t\)

Forecast errors:

augment(fit)
augment(fit) %>% filter(Country == "Sweden") %>%
  ggplot(aes(x = .resid)) +
  geom_histogram(bins = 20) +
  ggtitle("Histogram of residuals")

5.2 Are the model residuals auto-correlated?

augment(fit) %>% filter(Country == "Sweden") -> augSweden

augSweden %>%
  ACF(.resid) %>%
  autoplot() + ggtitle("ACF of residuals")

augment(fit3) %>% filter(Country == "Sweden") -> augSweden3

augSweden3 %>%
  ACF(.resid) %>%
  autoplot() + ggtitle("ACF of residuals")

6 Example: GDP, several models, several countries

library(tsibbledata) # Data sets package

nordic <- c("Sweden", "Denmark", "Norway", "Finland")

(global_economy %>% filter(Country %in% nordic) -> nordic_economy)
NA
nordic_economy %>% autoplot(GDP)

fitnord <- nordic_economy %>%
  model(
    trend_model = TSLM(GDP ~ trend()),
    trend_model_ln = TSLM(log(GDP) ~ trend()),
    ets = ETS(GDP ~ trend("A")),
    arima = ARIMA(GDP)
  )

fitnord
fitnord %>%
  select(arima) %>%
  coef()

Denmark: ARMA(1,1)

Finland: MA(2)

Norway: MA(1)

Sweden: MA(2)

nordic_economy %>%
  model(arima_constrained = ARIMA(GDP ~ pdq(1,0,2))) %>% select(arima_constrained) %>% coef()
It looks like you're trying to fully specify your ARIMA model but have not said if a constant should be included.
You can include a constant using `ARIMA(y~1)` to the formula or exclude it by adding `ARIMA(y~0)`.It looks like you're trying to fully specify your ARIMA model but have not said if a constant should be included.
You can include a constant using `ARIMA(y~1)` to the formula or exclude it by adding `ARIMA(y~0)`.It looks like you're trying to fully specify your ARIMA model but have not said if a constant should be included.
You can include a constant using `ARIMA(y~1)` to the formula or exclude it by adding `ARIMA(y~0)`.It looks like you're trying to fully specify your ARIMA model but have not said if a constant should be included.
You can include a constant using `ARIMA(y~1)` to the formula or exclude it by adding `ARIMA(y~0)`.4 errors (1 unique) encountered for arima_constrained
[4] Could not find an appropriate ARIMA model.
This is likely because automatic selection does not select models with characteristic roots that may be numerically unstable.
For more details, refer to https://otexts.com/fpp3/arima-r.html#plotting-the-characteristic-roots
fitnord %>% coef() 
fitnord %>%  glance()  
fitnord %>% filter(Country == "Denmark") %>% select(arima) %>% report()
Series: GDP 
Model: ARIMA(1,1,1) 

Coefficients:
          ar1     ma1
      -0.3898  0.7240
s.e.   0.2061  0.1434

sigma^2 estimated as 2.407e+20:  log likelihood=-1417.5
AIC=2840.99   AICc=2841.45   BIC=2847.12
fitnord %>%
  accuracy() %>%
  arrange(Country, MPE)

7 Statistical model

7.1 Formal model of data-generating process

Write down an equation (or set of equations) that represent the data-generating process formally.

For the electricity sales data, maybe the process looks like:

\[ y_t = Trend_t X Seasonal_t X Residual_t \] \[ y_t = \beta_0 + \beta_1 t + \beta_2 m + \varepsilon_t \]

# ETS forecasts
USAccDeaths %>%
  ets() %>%
  forecast() %>%
  autoplot()
str(taylor)
plot(taylor)

If applicable: describe any transformations of the data (e.g., differencing, taking logs) you need to make to get the data into a form (e.g., linear) ready for numerical analysis.

What kind of process is it? \(AR(p)\)? White noise with drift? Something else?

Write down an equation expressing each realization of the stochastic process \(y_t\) as a function of other observed data (which could include lagged values of \(y\)), unobserved parameters (\(\beta\)), and an error term (\(\varepsilon_t\)). Ex:

\[y = X\cdot\beta + \varepsilon\] Add a model of the error process. Ex: \(\varepsilon \sim N(0, \sigma^2 I_T)\).

7.2 Discussion of the statistical model

Describe how the formal statistical model captures and aligns with the narrative of the data-generating process. Flag any statistical challenges raised by the data generating process, e.g. selection bias; survivorship bias; omitted variables bias, etc.

8 Plan for data analysis

Describe what information you wish to extract from the data. Do you wish to… estimate the values of the unobserved model parameters? create a tool for forecasting? estimate the exceedance probabilities for future realizations of \(y_t\)?

Describe your plan for getting this information. OLS regression? Some other statistical technique?

If you can: describe briefly which computational tools you will use (e.g., R), and which packages you expect to draw on.

9 Submission requirements

Prepare your proposal using Markdown . (You may find it useful to generate your Markdown file from some other tool, e.g. R Markdown in R Studio.) Submit your proposal by pushing it to your repo within the course organization on Github. When your proposal is ready, notify the instructor by also creating a submission for this assignment on Collab. Please also upload a PDF version of your proposal to Collab as part of your submission.

10 Comment

Depending on your prior experience, you may find this assignment challenging. Treat this assignment as an opportunity to make progress on your own research program. Make your proposal as complete as you can. But note that this assignment is merely the First Draft. You will have more opportunity to refine your work over the next two months, in consultation with the instructor, your advisor, and your classmates.

11 References

Burnham, Kenneth P., and David R. Anderson. 2002. Model Selection and Multimodel Inference: A Practical Information-Theoretic Approach. 2nd ed. New York: Springer-Verlag. https://doi.org/10.1007/b97636.

LS0tCnRpdGxlOiAgICAgIlByb2plY3QgUHJvcG9zYWwgSW5zdHJ1Y3Rpb25zIHdpdGggZXhhbXBsZSBjb2RlIgppbnN0aXR1dGU6ICJTWVMgNTU4MSBUaW1lIFNlcmllcyAmIEZvcmVjYXN0aW5nLCBTcHJpbmcgMjAyMSIgCmF1dGhvcjogICAgICJJbnN0cnVjdG9yOiBBcnRodXIgU21hbGwiCmRhdGU6ICAgICAgICJWZXJzaW9uIG9mIGByIFN5cy5EYXRlKClgIgpvdXRwdXQ6IAogIGh0bWxfbm90ZWJvb2s6CiAgICBudW1iZXJfc2VjdGlvbnM6IHRydWUKICAgIHRvYzogeWVzCiAgICB0b2NfZGVwdGg6IDQKICAgIGNvZGVfZm9sZGluZzogc2hvdyAjIG9wdGlvbnM6IHNob3csIGhpZGUKICAgIGZpZ19jYXB0aW9uOiB5ZXMKICAjIGh0bWxfZG9jdW1lbnQ6CiAgIyAgICAgICBrZWVwX21kOiB5ZXMKICBwZGZfZG9jdW1lbnQ6IGRlZmF1bHQKYmlibGlvZ3JhcGh5OiAvVXNlcnMvQXJ0aHVyL0dpdFJlcG9zL1RlYWNoaW5nL3RpbWUtc2VyaWVzL3RzZXJpZXMuYmliCmxpbmstY2l0YXRpb25zOiB5ZXMKLS0tCgpJbiB0aGlzIGFzc2lnbm1lbnQgeW91IHdpbGwgZGV2ZWxvcCB5b3VyIGluaXRpYWwgY29uY2VwdCBub3RlIGludG8gYSBkcmFmdCBvZiBhIGZ1bGwgcHJvamVjdCBwcm9wb3NhbC4gVHJlYXQgdGhpcyBhc3NpZ25tZW50IGFzIGEgImRyeSBydW4iIGZvciBkZXZlbG9waW5nIGEgcHJvcG9zYWwgZm9yIGEgZ3JhbnQgb3IgZmVsbG93c2hpcCBhcHBsaWNhdGlvbiwgb3IgZm9yIHlvdXIgUGguRC4gcHJvc3BlY3R1cy4KCllvdXIgcHJvcG9zYWwgc2hvdWxkIGluY2x1ZGUgYXQgbGVhc3QgdGhlIGZvbGxvd2luZyBzZWN0aW9ucyBhbmQgaW5mb3JtYXRpb24uCgoqKkZyb250IG1hdHRlcjoqKiBEZXNjcmlwdGl2ZSB0aXRsZSwgeW91ciBuYW1lLCBkYXRlLCByZWZlcmVuY2UgdG8gIlNZUyA1NTgxIFRpbWUgU2VyaWVzICYgRm9yZWNhc3RpbmcsIFNwcmluZyAyMDIxIi4KCioqQWJzdHJhY3Q6KiogQSB2ZXJ5IGJyaWVmIHN1bW1hcnkgb2YgdGhlIHByb2plY3QuCgojIEludHJvZHVjdGlvbgoKR2l2ZSBhIG5hcnJhdGl2ZSBkZXNjcmlwdGlvbiBvZiB0aGUgcHJvYmxlbSB5b3UgYXJlIGFkZHJlc3NpbmcsIGFuZCB0aGUgbWV0aG9kcyB5b3Ugd2lsbCB1c2UgdG8gYWRkcmVzcyBpdC4gUHJvdmlkZSBjb250ZXh0OgoKLSAgIFdoYXQgaXMgdGhlIHF1ZXN0aW9uIHlvdSBhcmUgYXR0ZW1wdGluZyB0byBhbnN3ZXI/Ci0gICBXaHkgaXMgdGhpcyBxdWVzdGlvbiBpbXBvcnRhbnQ/IChXaG8gY2FyZXM/KQotICAgSG93IHdpbGwgeW91IGdvIGFib3V0IGF0dGVtcHRpbmcgdG8gYW5zd2VyIHRoaXMgcXVlc3Rpb24/CgpUaGlzIHdvcmsgYWRkcmVzc2VzIHRoZSBxdWVzdGlvbjogV2h5IGRvIHBlb3BsZSBub3QgdXNlIHByb2JhYmlsaXN0aWMgZm9yZWNhc3RzIGZvciBkZWNpc2lvbi1tYWtpbmcgW0BidXJuaGFtTW9kZWxTZWxlY3Rpb25NdWx0aW1vZGVsMjAwMl0/CgojIFRoZSBkYXRhIGFuZCB0aGUgZGF0YS1nZW5lcmF0aW5nIHByb2Nlc3MKCkRlc2NyaWJlIHRoZSBkYXRhIHNldCB5b3Ugd2lsbCBiZSBhbmFseXppbmcsIGFuZCB3aGVyZSBpdCBjb21lcyBmcm9tLCBob3cgaXQgd2FzIGdlbmVyYXRlZCBhbmQgY29sbGVjdGVkLiBJZGVudGlmeSB0aGUgc291cmNlIG9mIHRoZSBkYXRhLiBHaXZlIGEgbmFycmF0aXZlIGRlc2NyaXB0aW9uIG9mIHRoZSBkYXRhLWdlbmVyYXRpbmcgcHJvY2VzczogdGhpcyBwaWVjZSBpcyBjcml0aWNhbCAuCgpTaW5jZSB0aGVzZSB3aWxsIGJlIHRpbWUgc2VyaWVzIGRhdGE6IGlkZW50aWZ5IHRoZSBmcmVxdWVuY3kgb2YgdGhlIGRhdGEgc2VyaWVzIChlLmcuLCBob3VybHksIG1vbnRobHkpLCBhbmQgdGhlIHBlcmlvZCBvZiByZWNvcmQuCgpgYGB7ciBzZXQgdXAgY29kaW5nIGVudmlyb25tZW50LCBpbmNsdWRlPUZBTFNFLCBtZXNzYWdlPUZBTFNFfQojIGxpYnJhcnkoZHBseXIpIC0tIGRvbid0IG5lZWQgdGhpcyBpZiB5b3UgYXJlIGxvYWRpbmcgdGhlIGVudGlyZSAndGlkeXZlcnNlJyBzdWl0ZQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShsdWJyaWRhdGUpICMgRm9yIGVhc3kgaGFuZGxpbmcgb2YgdGltZS1pbmRleGVkIG9iamVjdHMKCiMgaWYoISgnZnBwMycgJWluJSBpbnN0YWxsZWQucGFja2FnZXMoKSkpIGluc3RhbGwucGFja2FnZXMoJ2ZwcDMnKQpsaWJyYXJ5KGZwcDMpCmBgYAoKYGBge3Igb3BlbiBjb25uZWN0aW9uIHRvIGRhdGFiYXNlLCBldmFsPUZBTFNFLCBpbmNsdWRlPUZBTFNFfQojIE9wZW4gY29ubmVjdGlvbiB0byBhIHJlbW90ZSBkYXRhYmFzZQojIE1ha2Ugc3VyZSB5b3VyIFZQTiBuZXR3b3JrIGNvbm5lY3Rpb24gaXMgYWN0aXZlIGlmIG5lZWRlZCEKCiMgaWYoISgnUlBvc3RncmVTUUwnICVpbiUgaW5zdGFsbGVkLnBhY2thZ2VzKCkpKSBpbnN0YWxsLnBhY2thZ2VzKCdSUG9zdGdyZVNRTCcpCmxpYnJhcnkoUlBvc3RncmVTUUwpCgojICJteV9wb3N0Z3Jlc19jcmVkZW50aWFscy5SIiBjb250YWlucyB0aGUgbG9nLWluIGluZm9ybWF0aW9uCnNvdXJjZSgiL1VzZXJzL0FydGh1ci9HaXRSZXBvcy9UZWFjaGluZy9teV9wb3N0Z3Jlc19kYl9jcmVkZW50aWFscy5SIikKCiMgT3BlbiBjb25uZWN0aW9uCmRiX2RyaXZlciA8LSBkYkRyaXZlcigiUG9zdGdyZVNRTCIpCmRiIDwtIGRiQ29ubmVjdChkYl9kcml2ZXIsdXNlcj11c2VyLCBwYXNzd29yZD1wYXNzd29yZCxkYm5hbWU9InBvc3RncmVzIiwgaG9zdD1ob3N0KQpybShwYXNzd29yZCkgCgojIGNoZWNrIHRoZSBjb25uZWN0aW9uOiBJZiBmdW5jdGlvbiByZXR1cm5zIHZhbHVlIFRSVUUsIHRoZSBjb25uZWN0aW9uIGlzIHdvcmtpbmcKZGJFeGlzdHNUYWJsZShkYiwgIm1ldGFkYXRhIikKYGBgCgpgYGB7ciByZXRyaWV2ZSBkYXRhIGZyb20gZGIsIGV2YWw9RkFMU0UsIG1lc3NhZ2U9RkFMU0V9CmVzYWxlcyA8LSBkYkdldFF1ZXJ5KGRiLCdTRUxFQ1QgKiBmcm9tIGVpYV9lbGVjX3NhbGVzX3ZhX2FsbF9tJykgIyBTUUwgY29kZSB0byByZXRyaWV2ZSBkYXRhIGZyb20gYSB0YWJsZSBpbiB0aGUgcmVtb3RlIGRhdGFiYXNlCiMgc3RyKGVzYWxlcykKZXNhbGVzIDwtIGFzX3RpYmJsZShlc2FsZXMpICMgQ29udmVydCBkYXRhZnJhbWUgdG8gYSAndGliYmxlJyBmb3IgdGlkeXZlcnNlIHdvcmsKIyBzdHIoZXNhbGVzKQpgYGAKCmBgYHtyIHNhdmUgZGF0YSBpbiBBcGFjaGUgQXJyb3cgZm9ybWF0LCBldmFsPUZBTFNFfQojIFJlZmVyZW5jZTogaHR0cHM6Ly9hcnJvdy5hcGFjaGUub3JnL2RvY3Mvci8KIyBpZighKCdhcnJvdycgJWluJSBpbnN0YWxsZWQucGFja2FnZXMoKSkpIGluc3RhbGwucGFja2FnZXMoJ2Fycm93JykKbGlicmFyeShhcnJvdykKd3JpdGVfZmVhdGhlcihlc2FsZXMsICJlc2FsZXMuZmVhdGhlciIpCmBgYAoKYGBge3IgY2xvc2UgZGIgY29ubmVjdGlvbiwgZXZhbD1GQUxTRX0KIyBDbG9zZSBjb25uZWN0aW9uIC0tIHRoaXMgaXMgZ29vZCBwcmFjdGljZQpkYkRpc2Nvbm5lY3QoZGIpCmRiVW5sb2FkRHJpdmVyKGRiX2RyaXZlcikKYGBgCgojIEV4cGxvcmF0b3J5IGRhdGEgYW5hbHlzaXMKCmBgYHtyIHJlYWQgaW4gZGF0YX0KbGlicmFyeShhcnJvdykKZXNhbGVzIDwtIHJlYWRfZmVhdGhlcigiZXNhbGVzLmZlYXRoZXIiKQoKc3RyKGVzYWxlcykKYGBgCgojIyBQcm92aWRlIGEgYnJpZWYgZXhhbXBsZSBvZiB0aGUgZGF0YSwgc2hvd2luZyBob3cgdGhleSBhcmUgc3RydWN0dXJlZC4KCmBgYHtyIHByaW50IHRoZSBkYXRhIGFzIGEgdGFibGV9CnByaW50KGVzYWxlcykKYGBgCgpgYGB7ciB1c2UgdGlkeXZlcnNlIHN5bnRheCB0byBwZXJmb3JtIHNvbWUgc2ltcGxlIGRhdGEgbWFuaXB1bGF0aW9uc30KIyBSZWZlcmVuY2VzOiBodHRwczovL3d3dy50aWR5dmVyc2Uub3JnLywgaHR0cHM6Ly9kcGx5ci50aWR5dmVyc2Uub3JnLwoKZXNhbGVzICU+JQogIGZpbHRlcih5ZWFyID09IDIwMTkpICU+JQogIGZpbHRlcih2YWx1ZSA+IDkwMDApICU+JQogIHByaW50KCkKCmVzYWxlcyAlPiUKICBncm91cF9ieShtb250aCkgJT4lCiAgc3VtbWFyaXNlKG1lYW4gPSBtZWFuKHZhbHVlKSkgLT4gbWVhbl9lc2FsZXNfYnlfbW9udGgKCmVzYWxlcyAlPiUKICBtdXRhdGUoc2FsZXNfVFdoID0gdmFsdWUvMTAwMCkgJT4lCiAgc2VsZWN0KC12YWx1ZSkKICAKIyBmaWx0ZXIoZGF0YSBvYmplY3QsIGNvbmRpdGlvbikgOiBzeW50YXggZm9yIGZpbHRlcigpIGNvbW1hbmQKYGBgCgojIyBQbG90IHRoZSB0aW1lIHNlcmllcy4KCmBgYHtyIHVzZSBnZ3Bsb3QyIHRvIGdlbmVyYXRlIGEgcGxvdH0KI1JlZmVyZW5jZTogaHR0cHM6Ly9nZ3Bsb3QyLnRpZHl2ZXJzZS5vcmcvCgpnZ3Bsb3QoZGF0YT1lc2FsZXMsIGFlcyh4PWRhdGUseT12YWx1ZSkpICsgCiAgZ2VvbV9saW5lKCkgKyB4bGFiKCJZZWFyIikgKyB5bGFiKCJWaXJnaW5pYSBtb250aGx5IHRvdGFsIGVsZWN0cmljaXR5IHNhbGVzIChHV2gpIikKCmBgYAoKYGBge3J9CiMgaW5zdGFsbC5wYWNrYWdlcygidHNpYmJsZSIpCmxpYnJhcnkodHNpYmJsZSkgIyBSZWZlcmVuY2U6IGh0dHBzOi8vdHNpYmJsZS50aWR5dmVydHMub3JnL2FydGljbGVzL2ludHJvLXRzaWJibGUuaHRtbAoKZXNhbGVzICU+JSBhc190c2liYmxlKGluZGV4ID0gZGF0ZSkgLT4gZXNhbGVzX3RibF90cwoKcHJpbnQoZXNhbGVzX3RibF90cykKYGBgCgpgYGB7cn0KbGlicmFyeShsdWJyaWRhdGUpICMgTWFrZSBpdCBlYXN5IHRvIGRlYWwgd2l0aCBkYXRlcwoKZXNhbGVzX3RibF90cyAlPiUgZmlsdGVyKG1vbnRoPT0zKQoKZXNhbGVzX3RibF90cyAlPiUgZmlsdGVyKG1vbnRoKGRhdGUpPT0zKQoKZXNhbGVzX3RibF90cyAlPiUKICBzZWxlY3QoZGF0ZSwgc2FsZXNfR1doID0gdmFsdWUpIC0+IGVsc2FsZXNfdGJsX3RzCgpwcmludChlbHNhbGVzX3RibF90cykKYGBgCgojIyBQZXJmb3JtIGFuZCByZXBvcnQgdGhlIHJlc3VsdHMgb2Ygb3RoZXIgZXhwbG9yYXRvcnkgZGF0YSBhbmFseXNpcwoKYGBge3IgbWFrZSBhIGhpc3RvZ3JhbSBvZiB0aGUgZGF0YX0KCmhpc3QoZWxzYWxlc190YmxfdHMkc2FsZXNfR1doLCBicmVha3M9NDApCmBgYAoKYGBge3J9CiMgaW5zdGFsbC5wYWNrYWdlcygiZmVhc3RzIiksIFJlZmVyZW5jZTogaHR0cHM6Ly9mZWFzdHMudGlkeXZlcnRzLm9yZy8KbGlicmFyeShmZWFzdHMpCgplbHNhbGVzX3RibF90cyAlPiUgCiAgbXV0YXRlKE1vbnRoID0geWVhcm1vbnRoKGRhdGUpKSAlPiUgCiAgYXNfdHNpYmJsZShpbmRleCA9IE1vbnRoKSAtPiB2YWVsc2FsZXNfdGJsX3RzCgoKdmFlbHNhbGVzX3RibF90cyAlPiUgZ2dfc2Vhc29uKHNhbGVzX0dXaCwgbGFiZWxzID0gImJvdGgiKSArIHlsYWIoIlZpcmdpbmlhIGVsZWN0cmljaXR5IHNhbGVzIChHV2gpIikKYGBgCgpgYGB7cn0KIyBpbnN0YWxsLnBhY2thZ2VzKCd0c2liYmxlZGF0YScpCmxpYnJhcnkodHNpYmJsZWRhdGEpCgphdXNfcHJvZHVjdGlvbgoKYXVzX3Byb2R1Y3Rpb24gJT4lIGdnX3NlYXNvbihFbGVjdHJpY2l0eSkKCmF1c19wcm9kdWN0aW9uICU+JSBnZ19zZWFzb24oQmVlcikKCgpgYGAKCmBgYHtyfQp2YWVsc2FsZXNfdGJsX3RzICU+JSAKICBnZ19zdWJzZXJpZXMoc2FsZXNfR1doKQoKIyBhdXNfcHJvZHVjdGlvbiAlPiUgZ2dfc3Vic2VyaWVzKEJlZXIpCmBgYAoKYGBge3IgcGxvdCBsYWdnZWQgdmFsdWVzfQp2YWVsc2FsZXNfdGJsX3RzICAlPiUgZmlsdGVyKG1vbnRoKE1vbnRoKSAlaW4lIGMoMyw2LDksMTIpKSAlPiUgZ2dfbGFnKHNhbGVzX0dXaCwgbGFncyA9IDE6MikKCnZhZWxzYWxlc190YmxfdHMgICU+JSBmaWx0ZXIobW9udGgoTW9udGgpID09IDEpICU+JSBnZ19sYWcoc2FsZXNfR1doLCBsYWdzID0gMToyKQpgYGAKCmBgYHtyfQp2YWVsc2FsZXNfdGJsX3RzICU+JSBBQ0Yoc2FsZXNfR1doKSAlPiUgYXV0b3Bsb3QoKQpgYGAKCmBgYHtyIHBlcmZvcm0gYXV0b21hdGVkIHRpbWUgc2VyaWVzIGRlY29tcG9zaXRpb259CgoKIyBkZWNvbXBvc2UodmFlbHNhbGVzX3RibF90cykKYGBgCgpgYGB7ciBwZXJmb3JtIGFkZGl0aXZlIFNUTCBkZWNvbXBvc2l0aW9uIG9mIHRoZSBWQSBlbGVjdHJpY2l0eSBzYWxlcyB0aW1lIHNlcmllc30KdmFlbHNhbGVzX3RibF90cyAlPiUKICBtb2RlbChTVEwoc2FsZXNfR1doIH4gdHJlbmQod2luZG93PTIxKSArIHNlYXNvbih3aW5kb3c9J3BlcmlvZGljJyksIHJvYnVzdCA9IFRSVUUpKSAlPiUKICBjb21wb25lbnRzKCkgJT4lCiAgYXV0b3Bsb3QoKQpgYGAKCmBgYHtyIHBlcmZvcm0gbXVsdGlwbGljYXRpdmUgU1RMIGRlY29tcG9zaXRpb24gb2YgdGhlIFZBIGVsZWN0cmljaXR5IHNhbGVzIHRpbWUgc2VyaWVzfQp2YWVsc2FsZXNfdGJsX3RzICU+JQogIG11dGF0ZShsbl9zYWxlc19HV2ggPSBsb2coc2FsZXNfR1doKSkgJT4lCiAgbW9kZWwoU1RMKGxuX3NhbGVzX0dXaCB+IHRyZW5kKHdpbmRvdz0yMSkgKyBzZWFzb24od2luZG93PSdwZXJpb2RpYycpLAogICAgcm9idXN0ID0gVFJVRSkpICU+JQogIGNvbXBvbmVudHMoKSAlPiUKICBhdXRvcGxvdCgpCmBgYAoKYGBge3J9CnZhZWxzYWxlc190YmxfdHMgJT4lCiAgZmVhdHVyZXMoc2FsZXNfR1doLCBmZWF0X3N0bCkKYGBgCgpgYGB7cn0KdmFlbHNhbGVzX3RibF90cyAlPiUKICBmZWF0dXJlcyhzYWxlc19HV2gsIGZlYXR1cmVfc2V0KHBrZ3M9ImZlYXN0cyIpKQpgYGAKCiMgRXhhbXBsZTogR3Jvc3MgRG9tZXN0aWMgUHJvZHVjdCBkYXRhCgojIyBFeHBsb3JhdG9yeSBkYXRhIGFuYWx5c2lzCgpgYGB7cn0KbGlicmFyeSh0c2liYmxlZGF0YSkgIyBEYXRhIHNldHMgcGFja2FnZQoKcHJpbnQoZ2xvYmFsX2Vjb25vbXkpCmBgYAoKYGBge3J9Cmdsb2JhbF9lY29ub215ICU+JSBmaWx0ZXIoQ291bnRyeT09IlN3ZWRlbiIpICU+JSBwcmludCgpCmBgYAoKYGBge3J9Cmdsb2JhbF9lY29ub215ICU+JQogIGZpbHRlcihDb3VudHJ5PT0iU3dlZGVuIikgJT4lCiAgYXV0b3Bsb3QoR0RQKSArCiAgZ2d0aXRsZSgiR0RQIGZvciBTd2VkZW4iKSArIHlsYWIoIiRVUyBiaWxsaW9ucyIpCmBgYAoKIyMgRml0dGluZyBkYXRhIHRvIHNpbXBsZSBtb2RlbHMKCmBgYHtyfQpnbG9iYWxfZWNvbm9teSAlPiUgbW9kZWwodHJlbmRfbW9kZWwgPSBUU0xNKEdEUCB+IHRyZW5kKCkpKSAtPiBmaXQKCmZpdAoKCmBgYAoKYGBge3J9CmZpdCAlPiUgZmlsdGVyKENvdW50cnkgPT0gIlN3ZWRlbiIpICU+JSByZXNpZHVhbHMoKQpgYGAKCmBgYHtyfQoKZml0ICU+JSBmaWx0ZXIoQ291bnRyeSA9PSAiU3dlZGVuIikgJT4lIHJlc2lkdWFscygpICU+JSBhdXRvcGxvdCgucmVzaWQpCmBgYAoKIyMjIFdvcmsgd2l0aCBsbihHRFApCgpgYGB7cn0KZ2xvYmFsX2Vjb25vbXkgJT4lCiAgZmlsdGVyKENvdW50cnk9PSJTd2VkZW4iKSAlPiUKICBhdXRvcGxvdChsb2coR0RQKSkgKwogIGdndGl0bGUoImxuKEdEUCkgZm9yIFN3ZWRlbiIpICsgeWxhYigiJFVTIGJpbGxpb25zIikKYGBgCgpgYGB7cn0KZ2xvYmFsX2Vjb25vbXkgJT4lCiAgbW9kZWwodHJlbmRfbW9kZWwgPSBUU0xNKGxvZyhHRFApIH4gdHJlbmQoKSkpIC0+IGxvZ2ZpdApgYGAKCmBgYHtyfQpsb2dmaXQgJT4lIGZpbHRlcihDb3VudHJ5ID09ICJTd2VkZW4iKSAlPiUgcmVzaWR1YWxzKCkgJT4lIGF1dG9wbG90KCkKYGBgCgpgYGB7cn0KZ2xvYmFsX2Vjb25vbXkgJT4lIG1vZGVsKHRyZW5kX21vZGVsID0gVFNMTShsb2coR0RQKSB+IGxvZyhQb3B1bGF0aW9uKSkpIC0+IGZpdDMKCmZpdDMgJT4lIGZpbHRlcihDb3VudHJ5ID09ICJTd2VkZW4iKSAlPiUgcmVzaWR1YWxzKCkgJT4lIGF1dG9wbG90KCkKCmBgYAoKIyBQcm9kdWNpbmcgZm9yZWNhc3RzCgpgYGB7cn0KZml0ICU+JSBmb3JlY2FzdChoID0gIjMgeWVhcnMiKSAtPiBmY2FzdDN5cnMKCmZjYXN0M3lycwoKYGBgCgpgYGB7cn0KCmZjYXN0M3lycyAlPiUgZmlsdGVyKENvdW50cnkgPT0gIlN3ZWRlbiIsIFllYXIgPT0gMjAyMCkgJT4lIHN0cigpCmBgYAoKYGBge3IgdmlzdWFsaXplIGZvcmVjYXN0c30KZmNhc3QzeXJzICU+JSAKICBmaWx0ZXIoQ291bnRyeT09IlN3ZWRlbiIpICU+JQogIGF1dG9wbG90KGdsb2JhbF9lY29ub215KSArCiAgZ2d0aXRsZSgiR0RQIGZvciBTd2VkZW4iKSArIHlsYWIoIiRVUyBiaWxsaW9ucyIpCmBgYAoKIyMgTW9kZWwgcmVzaWR1YWxzIHZzLiBmb3JlY2FzdCBlcnJvcnMKCk1vZGVsIHJlc2lkdWFsczoKCllvdXIgZGF0YTogJHlfMSwgeV8yLCBcbGRvdHMsIHlfVCQKCkZpdHRlZCB2YWx1ZXM6ICRcaGF0e3l9XzEsIFxoYXR7eX1fMiwgXGxkb3RzLCBcaGF0e3l9X1QkCgpNb2RlbCByZXNpZHVhbHM6ICRlX3QgPSB5X3QgLSBcaGF0e3l9X3QkCgpGb3JlY2FzdCBlcnJvcnM6CgpgYGB7cn0KYXVnbWVudChmaXQpCmBgYAoKYGBge3J9CmF1Z21lbnQoZml0KSAlPiUgZmlsdGVyKENvdW50cnkgPT0gIlN3ZWRlbiIpICU+JQogIGdncGxvdChhZXMoeCA9IC5yZXNpZCkpICsKICBnZW9tX2hpc3RvZ3JhbShiaW5zID0gMjApICsKICBnZ3RpdGxlKCJIaXN0b2dyYW0gb2YgcmVzaWR1YWxzIikKYGBgCgojIyBBcmUgdGhlIG1vZGVsIHJlc2lkdWFscyBhdXRvLWNvcnJlbGF0ZWQ/CgpgYGB7cn0KYXVnbWVudChmaXQpICU+JSBmaWx0ZXIoQ291bnRyeSA9PSAiU3dlZGVuIikgLT4gYXVnU3dlZGVuCgphdWdTd2VkZW4gJT4lCiAgQUNGKC5yZXNpZCkgJT4lCiAgYXV0b3Bsb3QoKSArIGdndGl0bGUoIkFDRiBvZiByZXNpZHVhbHMiKQpgYGAKCmBgYHtyfQphdWdtZW50KGZpdDMpICU+JSBmaWx0ZXIoQ291bnRyeSA9PSAiU3dlZGVuIikgLT4gYXVnU3dlZGVuMwoKYXVnU3dlZGVuMyAlPiUKICBBQ0YoLnJlc2lkKSAlPiUKICBhdXRvcGxvdCgpICsgZ2d0aXRsZSgiQUNGIG9mIHJlc2lkdWFscyIpCmBgYAoKCiMgRXhhbXBsZTogR0RQLCBzZXZlcmFsIG1vZGVscywgc2V2ZXJhbCBjb3VudHJpZXMKCgpgYGB7cn0KbGlicmFyeSh0c2liYmxlZGF0YSkgIyBEYXRhIHNldHMgcGFja2FnZQoKbm9yZGljIDwtIGMoIlN3ZWRlbiIsICJEZW5tYXJrIiwgIk5vcndheSIsICJGaW5sYW5kIikKCihnbG9iYWxfZWNvbm9teSAlPiUgZmlsdGVyKENvdW50cnkgJWluJSBub3JkaWMpIC0+IG5vcmRpY19lY29ub215KQoKYGBgCgpgYGB7cn0Kbm9yZGljX2Vjb25vbXkgJT4lIGF1dG9wbG90KEdEUCkKYGBgCgpgYGB7cn0KZml0bm9yZCA8LSBub3JkaWNfZWNvbm9teSAlPiUKICBtb2RlbCgKICAgIHRyZW5kX21vZGVsID0gVFNMTShHRFAgfiB0cmVuZCgpKSwKICAgIHRyZW5kX21vZGVsX2xuID0gVFNMTShsb2coR0RQKSB+IHRyZW5kKCkpLAogICAgZXRzID0gRVRTKEdEUCB+IHRyZW5kKCJBIikpLAogICAgYXJpbWEgPSBBUklNQShHRFApCiAgKQoKZml0bm9yZApgYGAKCmBgYHtyfQpmaXRub3JkICU+JQogIHNlbGVjdChhcmltYSkgJT4lCiAgY29lZigpCmBgYAoKCkRlbm1hcms6IEFSTUEoMSwxKQoKRmlubGFuZDogTUEoMikKCk5vcndheTogTUEoMSkKClN3ZWRlbjogTUEoMikKCmBgYHtyfQpub3JkaWNfZWNvbm9teSAlPiUKICBtb2RlbChhcmltYV9jb25zdHJhaW5lZCA9IEFSSU1BKEdEUCB+IHBkcSgxLDAsMikpKSAlPiUgc2VsZWN0KGFyaW1hX2NvbnN0cmFpbmVkKSAlPiUgY29lZigpCmBgYAoKYGBge3J9CmZpdG5vcmQgJT4lIGNvZWYoKSAKYGBgCgpgYGB7cn0KZml0bm9yZCAlPiUgIGdsYW5jZSgpICAKYGBgCgpgYGB7cn0KZml0bm9yZCAlPiUgZmlsdGVyKENvdW50cnkgPT0gIkRlbm1hcmsiKSAlPiUgc2VsZWN0KGFyaW1hKSAlPiUgcmVwb3J0KCkKYGBgCgpgYGB7cn0KZml0bm9yZCAlPiUKICBhY2N1cmFjeSgpICU+JQogIGFycmFuZ2UoQ291bnRyeSwgTVBFKQpgYGAKCgojIFN0YXRpc3RpY2FsIG1vZGVsCgojIyBGb3JtYWwgbW9kZWwgb2YgZGF0YS1nZW5lcmF0aW5nIHByb2Nlc3MKCldyaXRlIGRvd24gYW4gZXF1YXRpb24gKG9yIHNldCBvZiBlcXVhdGlvbnMpIHRoYXQgcmVwcmVzZW50IHRoZSBkYXRhLWdlbmVyYXRpbmcgcHJvY2VzcyBmb3JtYWxseS4KCkZvciB0aGUgZWxlY3RyaWNpdHkgc2FsZXMgZGF0YSwgbWF5YmUgdGhlIHByb2Nlc3MgbG9va3MgbGlrZToKCiQkIHlfdCA9IFRyZW5kX3QgWCBTZWFzb25hbF90IFggUmVzaWR1YWxfdCAkJCAkJCB5X3QgPSBcYmV0YV8wICsgXGJldGFfMSB0ICsgXGJldGFfMiBtICsgXHZhcmVwc2lsb25fdCAkJAoKYGBge3IsIGV2YWw9RkFMU0V9CiMgRVRTIGZvcmVjYXN0cwpVU0FjY0RlYXRocyAlPiUKICBldHMoKSAlPiUKICBmb3JlY2FzdCgpICU+JQogIGF1dG9wbG90KCkKYGBgCgpgYGB7ciwgZXZhbD1GQUxTRX0Kc3RyKHRheWxvcikKcGxvdCh0YXlsb3IpCmBgYAoKSWYgYXBwbGljYWJsZTogZGVzY3JpYmUgYW55IHRyYW5zZm9ybWF0aW9ucyBvZiB0aGUgZGF0YSAoZS5nLiwgZGlmZmVyZW5jaW5nLCB0YWtpbmcgbG9ncykgeW91IG5lZWQgdG8gbWFrZSB0byBnZXQgdGhlIGRhdGEgaW50byBhIGZvcm0gKGUuZy4sIGxpbmVhcikgcmVhZHkgZm9yIG51bWVyaWNhbCBhbmFseXNpcy4KCldoYXQga2luZCBvZiBwcm9jZXNzIGlzIGl0PyAkQVIocCkkPyBXaGl0ZSBub2lzZSB3aXRoIGRyaWZ0PyBTb21ldGhpbmcgZWxzZT8KCldyaXRlIGRvd24gYW4gZXF1YXRpb24gZXhwcmVzc2luZyBlYWNoIHJlYWxpemF0aW9uIG9mIHRoZSBzdG9jaGFzdGljIHByb2Nlc3MgJHlfdCQgYXMgYSBmdW5jdGlvbiBvZiBvdGhlciBvYnNlcnZlZCBkYXRhICh3aGljaCBjb3VsZCBpbmNsdWRlIGxhZ2dlZCB2YWx1ZXMgb2YgJHkkKSwgdW5vYnNlcnZlZCBwYXJhbWV0ZXJzICgkXGJldGEkKSwgYW5kIGFuIGVycm9yIHRlcm0gKCRcdmFyZXBzaWxvbl90JCkuIEV4OgoKJCR5ID0gWFxjZG90XGJldGEgKyBcdmFyZXBzaWxvbiQkIEFkZCBhIG1vZGVsIG9mIHRoZSBlcnJvciBwcm9jZXNzLiBFeDogJFx2YXJlcHNpbG9uIFxzaW0gTigwLCBcc2lnbWFeMiBJX1QpJC4KCiMjIERpc2N1c3Npb24gb2YgdGhlIHN0YXRpc3RpY2FsIG1vZGVsCgpEZXNjcmliZSBob3cgdGhlIGZvcm1hbCBzdGF0aXN0aWNhbCBtb2RlbCBjYXB0dXJlcyBhbmQgYWxpZ25zIHdpdGggdGhlIG5hcnJhdGl2ZSBvZiB0aGUgZGF0YS1nZW5lcmF0aW5nIHByb2Nlc3MuIEZsYWcgYW55IHN0YXRpc3RpY2FsIGNoYWxsZW5nZXMgcmFpc2VkIGJ5IHRoZSBkYXRhIGdlbmVyYXRpbmcgcHJvY2VzcywgZS5nLiBzZWxlY3Rpb24gYmlhczsgc3Vydml2b3JzaGlwIGJpYXM7IG9taXR0ZWQgdmFyaWFibGVzIGJpYXMsIGV0Yy4KCiMgUGxhbiBmb3IgZGF0YSBhbmFseXNpcwoKRGVzY3JpYmUgd2hhdCBpbmZvcm1hdGlvbiB5b3Ugd2lzaCB0byBleHRyYWN0IGZyb20gdGhlIGRhdGEuIERvIHlvdSB3aXNoIHRvLi4uIGVzdGltYXRlIHRoZSB2YWx1ZXMgb2YgdGhlIHVub2JzZXJ2ZWQgbW9kZWwgcGFyYW1ldGVycz8gY3JlYXRlIGEgdG9vbCBmb3IgZm9yZWNhc3Rpbmc/IGVzdGltYXRlIHRoZSBleGNlZWRhbmNlIHByb2JhYmlsaXRpZXMgZm9yIGZ1dHVyZSByZWFsaXphdGlvbnMgb2YgJHlfdCQ/CgpEZXNjcmliZSB5b3VyIHBsYW4gZm9yIGdldHRpbmcgdGhpcyBpbmZvcm1hdGlvbi4gT0xTIHJlZ3Jlc3Npb24/IFNvbWUgb3RoZXIgc3RhdGlzdGljYWwgdGVjaG5pcXVlPwoKSWYgeW91IGNhbjogZGVzY3JpYmUgYnJpZWZseSB3aGljaCBjb21wdXRhdGlvbmFsIHRvb2xzIHlvdSB3aWxsIHVzZSAoZS5nLiwgUiksIGFuZCB3aGljaCBwYWNrYWdlcyB5b3UgZXhwZWN0IHRvIGRyYXcgb24uCgojIFN1Ym1pc3Npb24gcmVxdWlyZW1lbnRzCgpQcmVwYXJlIHlvdXIgcHJvcG9zYWwgdXNpbmcgTWFya2Rvd24gLiAoWW91IG1heSBmaW5kIGl0IHVzZWZ1bCB0byBnZW5lcmF0ZSB5b3VyIE1hcmtkb3duIGZpbGUgZnJvbSBzb21lIG90aGVyIHRvb2wsIGUuZy4gUiBNYXJrZG93biBpbiBSIFN0dWRpby4pIFN1Ym1pdCB5b3VyIHByb3Bvc2FsIGJ5IHB1c2hpbmcgaXQgdG8geW91ciByZXBvIHdpdGhpbiB0aGUgY291cnNlIG9yZ2FuaXphdGlvbiBvbiBHaXRodWIuIFdoZW4geW91ciBwcm9wb3NhbCBpcyByZWFkeSwgbm90aWZ5IHRoZSBpbnN0cnVjdG9yIGJ5IGFsc28gY3JlYXRpbmcgYSBzdWJtaXNzaW9uIGZvciB0aGlzIGFzc2lnbm1lbnQgb24gQ29sbGFiLiBQbGVhc2UgYWxzbyB1cGxvYWQgYSBQREYgdmVyc2lvbiBvZiB5b3VyIHByb3Bvc2FsIHRvIENvbGxhYiBhcyBwYXJ0IG9mIHlvdXIgc3VibWlzc2lvbi4KCiMgQ29tbWVudAoKRGVwZW5kaW5nIG9uIHlvdXIgcHJpb3IgZXhwZXJpZW5jZSwgeW91IG1heSBmaW5kIHRoaXMgYXNzaWdubWVudCBjaGFsbGVuZ2luZy4gVHJlYXQgdGhpcyBhc3NpZ25tZW50IGFzIGFuIG9wcG9ydHVuaXR5IHRvIG1ha2UgcHJvZ3Jlc3Mgb24geW91ciBvd24gcmVzZWFyY2ggcHJvZ3JhbS4gTWFrZSB5b3VyIHByb3Bvc2FsIGFzIGNvbXBsZXRlIGFzIHlvdSBjYW4uIEJ1dCBub3RlIHRoYXQgdGhpcyBhc3NpZ25tZW50IGlzIG1lcmVseSB0aGUgRmlyc3QgRHJhZnQuIFlvdSB3aWxsIGhhdmUgbW9yZSBvcHBvcnR1bml0eSB0byByZWZpbmUgeW91ciB3b3JrIG92ZXIgdGhlIG5leHQgdHdvIG1vbnRocywgaW4gY29uc3VsdGF0aW9uIHdpdGggdGhlIGluc3RydWN0b3IsIHlvdXIgYWR2aXNvciwgYW5kIHlvdXIgY2xhc3NtYXRlcy4KCiMgUmVmZXJlbmNlcwo=